#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>
#include <mysql/mysql.h>
#include <time.h>
#include <sys/un.h>

#include"soapH.h"
#include"TesteService.nsmap"

#define PORT "4444" //nr. portului
#define BACKLOG 10 //nr de conexiuni
#define MAXMSG 1000 //lungimea maxima a mesajului
#define DEFAULTSOCKET "/tmp/DEFAULT.sock" // identificator de socket (este acelasi ca si in clienti)
FILE *soaplog ;
int id,ruleaza;

int InsertCommand(char *SQLStr)
{
  MYSQL *conn;
  MYSQL_RES *res;
  MYSQL_ROW row;
  
  char *server = "localhost";
  char *user = "root";
  char *password = "";
  char *database = "teste";
   
  conn = mysql_init(NULL);
   
  /* Conectarea la baza de date */
  if (!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0))
  {
    fprintf(stderr, "#%s\n", mysql_error(conn));
    return 1;
  }

  /* trimitere query SQL */
  if (mysql_query(conn, SQLStr))  
  {
    fprintf(stderr, "$%s\n", mysql_error(conn));
    return 1;
  }

  /*inchidere conexiune */
  
  /*mysql_free_result(res);*/
  
  mysql_close(conn);
  return 0;
}

char* SelectCommand(char *SQLStr)
{
  MYSQL *conn;
  MYSQL_RES *res;
  MYSQL_ROW row;
  char *ret =(char *)malloc(sizeof(char)*500);

  char *server = "localhost";
  char *user = "root";
  char *password = "";
  char *database = "teste";
   
  conn = mysql_init(NULL);
   
  if (!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0))
  {
    fprintf(stderr, "%s\n", mysql_error(conn));
    exit(0);
  }

  if (mysql_query(conn, SQLStr))
  {
    fprintf(stderr, "%s\n", mysql_error(conn));
    exit(0);
  }

  res = mysql_use_result(conn);
   
  row = mysql_fetch_row(res);
   
  strcpy(ret,row[0]);
      
  mysql_free_result(res);
  mysql_close(conn);
  return ret;
}

int este_in_sir(int sir[],int val,int n)
{
  int i;
  for(i=0;i<n;i++)
    if (val==sir[i])
      return 1;
  return 0;
}

int inregistreazaintrebare(char *intr,char *r1, char *r2, char *r3,char *corect)
{
  int n,val,i,id;
  char idintr[5],tmp[1000];
  srand(time(NULL));
  
  
  printf("\nintrebare:%s \nr1:%s \nr2:%s \nr3:%s \ncorect:%s",intr,r1,r2,r3,corect);
  
  /*inregistare raspunsuri si intrebari*/
 
  sprintf(tmp,"INSERT INTO intrebari(Intrebare,Puncte,corect) VALUES('%s','%d','%s')\0",intr,1,corect);
  if(InsertCommand(tmp)!=0)
    return -1;
  else
    id=atoi(SelectCommand("SELECT MAX(ID) FROM intrebari"));

sprintf(tmp,"INSERT INTO raspunsuri(IDIntrebare,Raspuns,nr) VALUES('%d','%s','%d')\0",id,r1,1);
  if(InsertCommand(tmp)!=0)
    return -1;
sprintf(tmp,"INSERT INTO raspunsuri(IDIntrebare,Raspuns,nr) VALUES('%d','%s','%d')\0",id,r2,2);
  if(InsertCommand(tmp)!=0)
    return -1;
sprintf(tmp,"INSERT INTO raspunsuri(IDIntrebare,Raspuns,nr) VALUES('%d','%s','%d')\0",id,r3,3);
  if(InsertCommand(tmp)!=0)
    return -1; 

  return id;
  return -1;
}

/*soap*/

/* inregistreaza clientul
userid= idul atribuit
*/
int mySpace__inregistreaza(struct soap* soap, struct inregistreazaType *pers, struct inregistreazaResponseType *userid)
{
//  char *nume,char *prenume, char *cnp;
//  long userid;


  int uid=inregistreaza(pers->nume, pers->prenume, pers->cnp);
  if (uid==-1)
  {
    printf("Eroare la inregistrare!!!");
    return -1;
  }
  else{
  printf("Inregistreaza: %s; %s; %s;#%d\n", pers->nume, pers->prenume, pers->cnp ,uid);
  userid->userid = uid;
  return SOAP_OK;
  }
}

/*
 treateaza cererea de raspuns a clientului
*/
int mySpace__raspunde(struct soap* soap, struct raspundeType *rasp, struct raspundeResponseType *control)
{
//	long userid;
//	char **rasp,char **nrintr,char **control;

	printf("Raspunde: %s;%s;#%ld\n",rasp->rasp,rasp->nrintr,rasp->userid);
	
	
	char tmp[500];
  int id_intr;
  
  
  sprintf(tmp,"UPDATE intr_alese SET Raspuns='%s' WHERE nr=%s AND IDUtilizator=%ld",rasp->rasp,rasp->nrintr,rasp->userid);
  if(InsertCommand(tmp)!=0)
    return -1;
  sprintf(tmp,"SELECT IDIntrebare FROM intr_alese WHERE nr=%s AND IDUtilizator=%ld",rasp->nrintr, rasp->userid);
  id_intr=atoi(SelectCommand(tmp));
  
  sprintf(tmp,"UPDATE intrebari as a,utilizatori as b SET b.Punctaj=b.Punctaj+a.Puncte WHERE a.ID=%d AND a.corect=%s AND b.ID=%ld\0",id_intr,rasp->rasp,rasp->userid);
  if(InsertCommand(tmp)!=0)
    return -1;
  control->control="true";
  return SOAP_OK;	
}

/*
trateaza cererea de "urmatoarea intrebare" a clientului
*/

int mySpace__cereintrebare(struct soap* soap, struct cereintrebareType *cere, struct cereintrebareResponseType *response)
{
  char tmp[1000],intrebare[500],rasp1[300],rasp2[300],rasp3[300];
  int id_intr;
  
  printf("Cerereintrebare: %s;    id:%ld\n",cere->nrintr,cere->userid);
  
  /*selectare intrebare cu raspunsuri din baza de date*/

  sprintf(tmp,"SELECT IDIntrebare FROM intr_alese WHERE nr=%s AND IDUtilizator=%ld",cere->nrintr,cere->userid);
  id_intr=atoi(SelectCommand(tmp));
  
  sprintf(tmp,"SELECT Intrebare FROM intrebari WHERE ID=%d",id_intr);
  strcpy(intrebare,SelectCommand(tmp));
  sprintf(tmp,"SELECT Raspuns FROM raspunsuri WHERE IDIntrebare=%d AND nr=1",id_intr);
  strcpy(rasp1,SelectCommand(tmp));
  sprintf(tmp,"SELECT Raspuns FROM raspunsuri WHERE IDIntrebare=%d AND nr=2",id_intr);
  strcpy(rasp2,SelectCommand(tmp));
  sprintf(tmp,"SELECT Raspuns FROM raspunsuri WHERE IDIntrebare=%d AND nr=3",id_intr);
  strcpy(rasp3,SelectCommand(tmp));
  
  sprintf(tmp,"nr=%s&intr=%s&r1=%s&r2=%s&r3=%s\0",cere->nrintr,intrebare,rasp1,rasp2,rasp3);
//in response returneaza intrebarea solicitata
  response->response=(char *)soap_malloc(soap,strlen(tmp)+1);
  strcpy(  response->response, tmp);
  return SOAP_OK;
}

/*
trateaza cererea de numar actual de puncte a clientului si o returneaza in nrpct
*/

int mySpace__numarpuncte(struct soap* soap, struct numarpuncteType *user, struct numarpuncteResponseType *puncte)
{
   char tmp[100],nrp[5];
  printf("Numarpuncte   id:%ld\n",user->userid);
  
  sprintf(tmp,"SELECT Punctaj FROM utilizatori where ID=%ld",user->userid);
  strcpy(nrp,SelectCommand(tmp));
  puncte->nrpct=(char *)soap_malloc(soap, strlen(nrp)+1);
  strcpy(puncte->nrpct, nrp);
  return SOAP_OK;
}
/*
 : treateaza cererea de numar final de puncte a clientului si o returneaza in nrpct
*/
int mySpace__numarpunctefinal(struct soap* soap, struct numarpunctefinalType *userid, struct numarpunctefinalResponseType *nrpctf)
{
   char tmp[100],nrp[5];
  printf("Numarpunctefinal   id:%ld\n",userid->userid);
  
    sprintf(tmp,"SELECT Punctaj FROM utilizatori where ID=%ld",userid->userid);
  strcpy(nrp,SelectCommand(tmp));
  nrpctf->nrpct=(char *)soap_malloc(soap,strlen(nrp)+1);
  strcpy(nrpctf->nrpct, nrp);
  /*ruleaza=0;*/
  return SOAP_OK;
}
/*end soap*/

int inregistreaza(char *nume, char *prenume, char *cnp)
{
  int n,val,i,iduri_intrebari[26],nr_aleatoare[26];
  char idintr[5],tmp[100];
  srand(time(NULL));
  for(i=0;i<10;i++)
  {
    iduri_intrebari[i]=0;
    nr_aleatoare[i]=0;
  }
  
  printf("\nnume:%s\nprenume: %s\ncnp: %s\n",nume,prenume,cnp);
  
  /*inregistare nume,prenume si cnp utilizator*/
 
  sprintf(tmp,"INSERT INTO utilizatori(Nume,Prenume,CNP) VALUES('%s','%s','%s')\0",nume,prenume,cnp);
  if(InsertCommand(tmp)!=0)
    return -1;
  else
    id=atoi(SelectCommand("SELECT MAX(ID) FROM utilizatori"));

  /*generare aleatoare a 10 de intrebari*/

  n=atoi(SelectCommand("SELECT COUNT(*) FROM intrebari"));
  for(i=0;i<10;i++)
  {
    val=(rand()%n+1);
    while(este_in_sir(nr_aleatoare,val,i)==1)
    {val=(rand()%n+1);}
    nr_aleatoare[i]=val;
    sprintf(tmp,"SELECT DISTINCT ID FROM intrebari ORDER BY ID LIMIT %d,1",val-1);
    iduri_intrebari[i]=atoi(SelectCommand(tmp));
  }
   for(i=0;i<10;i++)
   {
     //printf("\n%d,",iduri_intrebari[i]);
   }
  
  /*salvare intrebari in tabelul intr_alese*/ 

  for(i=0;i<10;i++)
  {
    sprintf(tmp,"INSERT INTO intr_alese(IDIntrebare,IDUtilizator,nr,Raspuns) VALUES(%d,%d,%d,'0')\0",iduri_intrebari[i],id,i+1);
    if(InsertCommand(tmp)!=0)
      return -1;
  }
  
  return id;
  return -1;
}

// : trateaza cererea de raspuns
int raspunde(char *rasp, char *nrintr)
{
  char tmp[500];
  int id_intr;
  printf("\nid:%d\nrasp: %s\nnrintr: %s\n",id,rasp,nrintr);
 
 
  sprintf(tmp,"UPDATE intr_alese SET Raspuns='%s' WHERE nr=%s AND IDUtilizator=%d",rasp,nrintr,id);
  if(InsertCommand(tmp)!=0)
    return -1;
  sprintf(tmp,"SELECT IDIntrebare FROM intr_alese WHERE nr=%s AND IDUtilizator=%d",nrintr,id);
  id_intr=atoi(SelectCommand(tmp));
  sprintf(tmp,"UPDATE intrebari as a,utilizatori as b SET b.Punctaj=b.Punctaj+a.Puncte WHERE a.ID=%d AND a.corect='%s' AND b.ID=%d",id_intr,rasp,id);
  if(InsertCommand(tmp)!=0)
    return -1;
   
  return id;
  return -1;
}

// : trateaza cererea de "urmatoarea intrebare"
int cereintrebare( char *nrintr,int fd)
{
  char tmp[1000],intrebare[500],rasp1[300],rasp2[300],rasp3[300];
  int id_intr;
  
  printf("\nid:%d\nnrintr: %s\n",id,nrintr);
  
  /*selectare intrebare cu raspunsuri din baza de date*/

  sprintf(tmp,"SELECT IDIntrebare FROM intr_alese WHERE nr=%s AND IDUtilizator=%d",nrintr,id);
  id_intr=atoi(SelectCommand(tmp));
  
  sprintf(tmp,"SELECT Intrebare FROM intrebari WHERE ID=%d",id_intr);
  strcpy(intrebare,SelectCommand(tmp));
  sprintf(tmp,"SELECT Raspuns FROM raspunsuri WHERE IDIntrebare=%d AND nr=1",id_intr);
  strcpy(rasp1,SelectCommand(tmp));
  sprintf(tmp,"SELECT Raspuns FROM raspunsuri WHERE IDIntrebare=%d AND nr=2",id_intr);
  strcpy(rasp2,SelectCommand(tmp));
  sprintf(tmp,"SELECT Raspuns FROM raspunsuri WHERE IDIntrebare=%d AND nr=3",id_intr);
  strcpy(rasp3,SelectCommand(tmp));
  
  sprintf(tmp,"intr#nr=%s&intr=%s&r1=%s&r2=%s&r3=%s\n\0",nrintr,intrebare,rasp1,rasp2,rasp3);
  if(send(fd,tmp,strlen(tmp),0)==-1)
    perror("send");
  
  return id;
  return -1;
}

 // trateaza cererea de a vizualiza numarul de puncte in momentul de fata
int numarpuncte(int fd)
{
  
  char tmp[100],nrpct[5],ret[20];
  printf("\nid:%d\n",id);
  
  sprintf(tmp,"SELECT Punctaj FROM utilizatori where ID=%d",id);
  strcpy(nrpct,SelectCommand(tmp));
  sprintf(ret,"nrpct#nrpct=%s\n",nrpct);
  if(send(fd,ret,strlen(ret),0)==-1)
    perror("send");
  return id;
  return -1;
}

 // trateaza cererea de a vizualiza numarul de puncte final si INCHIDE CONEXIUNEA!
int numarpunctefinal(int fd)
{
  
  char tmp[100],nrpct[5],ret[20];
  printf("\nid:%d\n",id);
  
  sprintf(tmp,"SELECT Punctaj FROM utilizatori where ID=%d",id);
  strcpy(nrpct,SelectCommand(tmp));
  sprintf(ret,"nrpctfin#nrpct=%s\n",nrpct);
  if(send(fd,ret,strlen(ret),0)==-1)
    perror("send");
  ruleaza=0;
  return id;
  return -1;
}

/*primeste intrebare+ raspunsuri+ etc si le parseaza in tokenuri*/
int regintr(char * str)
{
  int i;
  char *asd, val[1000][1000],r1[300],r2[300],r3[300],corect[5],intr[500];
  
  asd=strtok(str,"&");//imparte intrebarea si rasp dupa &-uri
  for(i=0;asd!=NULL;i++)
  {
    strcpy(val[i],asd);
    asd=strtok(NULL,"&");
  }
  for(i=0;i<5;i++)
  {
    asd=strtok(val[i],"=");
    if (strcmp(asd,"intr")==0)
      strcpy(intr,strtok(NULL,"="));
    else if (strcmp(asd,"r1")==0)
      strcpy(r1,strtok(NULL,"="));
    else if (strcmp(asd,"r2")==0)
      strcpy(r2,strtok(NULL,"="));
   else if (strcmp(asd,"r3")==0)
      strcpy(r3,strtok(NULL,"="));
else if (strcmp(asd,"corect")==0)
      strcpy(corect,strtok(NULL,"="));
    }
    printf ("inregistrare intrebare: %d\n", inregistreazaintrebare(intr,r1,r2,r3,corect));//apeleaza functia care introduce in tabele, trimitandu-i ca parametri
    //intrebarea, rasp, si raspunsul corect
  return 0;
}

 /* inregistreaza clientul de socket normal*/
int reg(char * str,int fd)
{
  int i;
  char *asd, val[100][100],nume[15],prenume[15],cnp[13];
  
  asd=strtok(str,"&");
  for(i=0;asd!=NULL;i++)
  {
    strcpy(val[i],asd);
    asd=strtok(NULL,"&");
  }
  for(i=0;i<3;i++)
  {
    asd=strtok(val[i],"=");
    if (strcmp(asd,"nume")==0)
      strcpy(nume,strtok(NULL,"="));
    else if (strcmp(asd,"prenume")==0)
      strcpy(prenume,strtok(NULL,"="));
    else if (strcmp(asd,"cnp")==0)
      strcpy(cnp,strtok(NULL,"="));
    }
    printf ("inregistrare: %d\n", inregistreaza(nume, prenume,cnp));
  return 0;
}

/* 
  primeste raspunsul clientului de server prin socket si il parseaza dupa care apeleaza 
functia "raspunde"
*/
int rasp(char *str, int fd)
{
  int i;
  char *asd, val[100][100],rasp[5],nrintr[5];
  
  asd=strtok(str,"&");
  for(i=0;asd!=NULL;i++)
  {
    strcpy(val[i],asd);
    asd=strtok(NULL,"&");
  }
  for(i=0;i<2;i++)
  {
    asd=strtok(val[i],"=");
    if (strcmp(asd,"rasp")==0)
      strcpy(rasp,strtok(NULL,"="));
    else if (strcmp(asd,"nrintr")==0)
      strcpy(nrintr,strtok(NULL,"="));
    }
    printf ("raspunde: %d\n", raspunde(rasp,nrintr));
  return 0;
}

/*
  primeste cererea de a da urmatoarea intrebare de la clientul de server prin socket
*/
int intrreq(char *str, int fd)
{
  int i;
  char *asd, val[100][100],nrintr[5];
  
  asd=strtok(str,"&");
  for(i=0;asd!=NULL;i++)
  {
    strcpy(val[i],asd);
    asd=strtok(NULL,"&");
  }
  for(i=0;i<1;i++)
  {
    asd=strtok(val[i],"=");
//   nrintr= numarul intrebarii pe care o cere clientul din cele 26 selectate pt el cand a fost inregistrat
    if (strcmp(asd,"nrintr")==0)
      strcpy(nrintr,strtok(NULL,"="));
    }
    printf ("cereintrebare: %d\n", cereintrebare(nrintr,fd));
  return 0;
}

 // primeste cererea de a afla punctajul in momentul de fata de la clientul de socketuri si o trimite mai departe
//la "numarpuncte"
int nrpct( int fd)
{
  printf ("numarpuncte: %d\n", numarpuncte(fd));
  return 0;
}

 // primeste cererea de a afla punctajul final de la clientul de socketuri si o trimite mai departe
//la "numarpunctefinal"
int nrpctfin(int fd)
{
  printf ("numarpunctefinal: %d\n", numarpunctefinal(fd));
  return 0;
}


/*   citeste o comanda de la un client de socket*/
int citeste (int fd)
{
  char buffer[MAXMSG];
  char val[1000][1000];
  char *asd;
  int nb,i;
  
//   citeste o comanda 
  nb = read (fd, buffer, MAXMSG);
  if (nb < 0)
  {
    perror ("eroare la read:");
    exit (EXIT_FAILURE);
  }
  else if (nb == 0)
  {
    ruleaza=0;
    return -1;
  }
  else
  {
    /* prelucrare date citite */
    buffer [nb-1] = 0 ;
 
//   parseaza comanda dupa #
    asd=strtok(buffer,"#");
    for(i=0;asd!=NULL;i++)
    {
      strcpy(val[i],asd);
      asd=strtok(NULL,"#");
    }
   
    printf("%s",val[0]);
    
    if(strcmp(val[0],"reg")==0)
      reg(val[1],fd); //   inregistreaza utilizator
    else if(strcmp(val[0],"rasp")==0)
      rasp(val[1],fd); //   trimite raspunsul
    else if(strcmp(val[0],"intrreq")==0)
      intrreq(val[1],fd);//   cere urmatoarea intrebare
    else if(strcmp(val[0],"nrpct")==0)
      nrpct(fd); //   cere numarul de puncte
    else if(strcmp(val[0],"nrpctfin")==0)
      nrpctfin(fd);  // cere numarul de puncte final
    return 0;
  }
}

void sigchld_handler(int s)
{
  while(waitpid(-1,NULL,WNOHANG)>0);
}

void *get_in_addr(struct sockaddr*sa)
{
  if(sa->sa_family==AF_INET)
  {
    return &(((struct sockaddr_in *)sa)->sin_addr);
  }
  return &(((struct sockaddr_in6 *)sa)->sin6_addr);
}

/*
  server prin socketuri (server normal :-D)
*/

int inet_sock()
{
  int sockfd, new_fd; /*descriptori socket pr proces tata si fiu*/
  struct addrinfo hints, *servinfo, *p;
  struct sockaddr_storage their_addr; /*informatii de adresa ale conectorului*/
  socklen_t sin_size;
  struct sigaction sa;
  int yes=1;
  char s[INET6_ADDRSTRLEN];
  int rv;
  memset(&hints,0,sizeof hints);
  hints.ai_family=AF_UNSPEC;
  hints.ai_socktype=SOCK_STREAM;
  hints.ai_flags=AI_PASSIVE;

  if ((rv=getaddrinfo(NULL,PORT,&hints,&servinfo))!=0)
  {
    fprintf(stderr,"getaddrinfo: %s\n",gai_strerror(rv));
    return 1;
  }

  for(p=servinfo;p!=NULL;p=p->ai_next)
  {
    if((sockfd=socket(p->ai_family,p->ai_socktype,p->ai_protocol))==-1) //deschiderea socket-ului
    {
      perror("server_socket");
      continue;
    }

    if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int))==-1)
    {
      perror("setsockopt");
      exit(1);
    }

    /*legarea secket-ului la adresa curenta*/
    if(bind(sockfd,p->ai_addr,p->ai_addrlen)==-1)
    {
      close(sockfd);
      perror("server: bind");
      continue;
    }
    break;
  }

  if (p==NULL)
  {
    fprintf(stderr,"server: failed to  bind\n");
    return 2;
  }

  freeaddrinfo(servinfo); /*stergem structura deoarece nu mai foloseste*/

  /*asteptare conexiuni*/
  if(listen(sockfd,BACKLOG)==-1)
  {
    perror("listen");
    exit(1);
  }

  sa.sa_handler=sigchld_handler;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags=SA_RESTART;


  if(sigaction(SIGCHLD, &sa, NULL)==-1)
  {
    perror("sigaction");
    exit(1);
  }

  printf("Serverul asteapta conexiuni...\n");

  while(1) /*ciclu pentru accept*/
  {
    sin_size=sizeof their_addr;
    new_fd=accept(sockfd,(struct sockaddr *) &their_addr, &sin_size);
    if(new_fd==-1)
    {
      perror("accept");
      continue;
    }
    /*convertire adrese pentru afisare*/
    inet_ntop(their_addr.ss_family,get_in_addr((struct sockaddr *) &their_addr),s, sizeof s);
    printf("server: Conexiune stabilita cu %s\n",s);
    if(!fork()) /*proces copil*/
    {
      close(sockfd); /*nu mai are nevoie de ascultator*/
      ruleaza=1;
      while(ruleaza==1)
      {
	if(citeste(new_fd)==-1)
	{
	  perror("citeste");
	}
      }

      close(new_fd);
      exit(0);
    }
    close(new_fd); /*parintele nu are nevoie de acest descriptor*/
  }
  return 0;
}


/*asculta comenzile de la client si raspunde*/
int local_server_read (int fd)
{
    char buffer[MAXMSG];
    int nb,length,i;
    char *text, *asd;
    char val[1000][1000];
  //citeste cati bytes are urmatoarea comanda 
  nb = read (fd, &length, sizeof (length));
  if (nb < 0)
  {
    perror ("eroare la read:");
    exit (EXIT_FAILURE);
  }
  else if (nb == 0)
  {
    //ruleaza=0;
    return -2;
  }
  else
  {//stiind cati bytes asre comanda, aloca spatiu pt comanda dupa care o citeste
    text = (char*) malloc (length);
    read (fd, text, length);
    printf ("Textul transmis: %s\n", text);
    
    if ((strcmp (text, "quit"))==0)
    {
      printf("Serverul local a fost oprit\n");
      ruleaza=0;
      free(text);
      unlink (DEFAULTSOCKET);
      return 0;
    }
    //imparte comanda dupa #-uri
    asd=strtok(text,"#");
    for(i=0;asd!=NULL;i++)
    {
//in val retine comanda + parametrii (val[0] e comanda)
      strcpy(val[i],asd);
      asd=strtok(NULL,"#");
    }
   
    printf("%s",val[0]);
    
    if(strcmp(val[0],"regintr")==0)
      regintr(val[1]);
    else
      printf("Eroare la inregistrarea intrebarii\n");
     
    
    free(text);
    return 0;
  }
    return 0;
}


/*
serverul local(comunicare intre procese de pe acelasi comp) = server de administrare
*/
int local_sock()
{
  const char* const socket_name = DEFAULTSOCKET;// acelasi ca si in clientul local
  int socket_fd;
  struct sockaddr_un name;
  int client_sent_quit_message;
  struct sockaddr_un client_name;
  socklen_t client_name_len;
  int client_socket_fd;
  socket_fd = socket (PF_LOCAL, SOCK_STREAM, 0);// se creaza un socket local
  
  name.sun_family = AF_LOCAL;
  strcpy (name.sun_path, socket_name);
  

   if(bind (socket_fd, (struct sockaddr *) &name, SUN_LEN (&name))==-1)
    {
      close(socket_fd);
      perror("server: bind");
    }
  
// se porneste serverul.  
   if(listen(socket_fd,BACKLOG)==-1)
  {
    perror("listen");
    exit(1);
  }
 

 
  while(1)
  {

    client_name_len=sizeof client_name;
//accepta client nou
    client_socket_fd = accept (socket_fd,(struct sockaddr *) &client_name, &client_name_len);
    if(client_socket_fd==-1)
    {
      perror("accept");
      continue;
    }
    printf("Conexiune acceptata\n");
    if(!fork()) /*proces copil*/
    {
//se creaza un proces copil care trateaza conexiunea cu clientul
      close(socket_fd); /*nu mai are nevoie de ascultator*/
      ruleaza=1;
      while(ruleaza==1)
      {
	if(local_server_read(client_socket_fd)==-1)
	{
	  perror("citeste");
	
	}
      }

      close(client_socket_fd);
      exit(0);
    }
  
    close(client_socket_fd); /*parintele nu */

  }
      unlink (DEFAULTSOCKET);
  return 0;
}


 /* serverul de soap*/
int soap_server()
{
  struct soap soap;
	int m,s,port;
//	port = *(int *)(args);
	soap_init(&soap); //   initializeaza contextul pentru server
	
	//SoapLog (EasySoap Web service engine only) The file path for SoapLog. To disable the log, enter "".
	soaplog = fopen ("soapserve.log", "a+") ;
	soap.bind_flags=SO_REUSEADDR ;
  	m = soap_bind (&soap, "127.0.0.1", port, 100) ;

	m=soap_bind(&soap, NULL /*ANY!*/,4445,100); //   leaga serverul la o adresa fizica
// si il porneste
	if(m<0)
	//if (!soap_valid_socket(m)) 
	{
		soap_print_fault(&soap,stderr);
		//soap_print_fault (&soap, soaplog) ; 
		exit(1);
	}
	for(;;)
	{
		s=soap_accept(&soap); // accepta conexiune de la client
		if(s<0)
			soap_print_fault(&soap,stderr);
			//{
			//	soap_print_fault (&soap, soaplog); break ; 
			//}
		else
		{
			soap_serve(&soap); // trateaza cererea (metoda generata)
		}

		//if (soap_serve (&soap) != SOAP_OK) 
		//	soap_print_fault (&soap, soaplog) ;

		soap_destroy(&soap); // inchide socketul clientului 
		soap_end(&soap);  // curata pe acolo
	}
	soap_done(&soap);  // inchide serverul 
	return 0;
}

/*
  cand este apelata aceasta functie se paraseste aplicatia
*/
void quitsignal() 
{
  signal(SIGINT,quitsignal);
  unlink (DEFAULTSOCKET);
  exit(0);
}

int main(void)
{
  
  signal(SIGINT,quitsignal); //cand userul da ctrl+C se apeleaza quitsignal
  if(!fork())
    return local_sock(); //server administrare
  else
  {
    if(!fork())
      return soap_server();  //server soap
    else
      return inet_sock();  //server de sockets
  }
}

/*compilare
  gcc server.c soapC.c soapServer.c $(mysql_config --cflags) $(mysql_config --libs) -l gsoap -o server
*/
